package com.jule.teenpatti.mail.service;

import JoloProtobuf.AuthSvr.JoloAuth;
import com.jule.core.common.log.LoggerUtils;
import com.jule.core.jedis.StoredObjManager;
import com.jule.core.utils.TimeUtil;
import com.jule.teenpatti.base.dao.bean.User;
import com.jule.teenpatti.base.enums.RedisConst;
import com.jule.teenpatti.mail.dao.DBUtil;
import com.jule.teenpatti.mail.dao.bean.*;
import com.jule.teenpatti.mail.model.MailArgsMap;
import com.jule.teenpatti.mail.model.MailConfigMap;
import com.jule.teenpatti.mail.model.UserAwardMap;
import com.jule.teenpatti.mail.model.UserMailMap;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

@Slf4j
public class MailService {

    /**
     * 所有玩家
     * 加载有效时间段内的邮件领取信息
     */
    public void init() {
        if (StoredObjManager.setnx(RedisConst.MAIL_USER_LOADING.getProfix(),
                RedisConst.MAIL_USER_LOADING.getField()) == 0L) {//两个小时内不重复加载
            return;
        }
        StoredObjManager.setEx(RedisConst.MAIL_USER_LOADING.getProfix(),
                RedisConst.MAIL_USER_LOADING.getField(), 60 * 60 * 2);
        //加载领取记录
        loadMailUserAwardLog();
    }

    /***
     * 根据userId加载DB中的邮件列表
     * @param userId
     */
    public void loadMailByUserId(String userId) {
        LoggerUtils.mailLog.info("loadMailByUserId：{}", userId);
        List<MailUserModel> list = DBUtil.getMailUserFromDb(userId, System.currentTimeMillis());
        if (list == null) {
            return;
        }
        UserMailMap userMailMap = new UserMailMap();
        userMailMap.add(list);

        //并检测有没有新的要加入的邮件
        checkNewMail(userId, userMailMap);
        //保存
        saveUserMailMap(userId, userMailMap);
    }

    /**
     * 获取缓存中的邮件
     *
     * @param userId
     * @return
     */
    public List<JoloAuth.JoloAuth_MailItem> getMailListByUserId(String userId) {
        List<JoloAuth.JoloAuth_MailItem> list = new ArrayList<>();
        UserMailMap userMailMap = getByUserId(userId);
        //if (userMailMap == null) {
        loadMailByUserId(userId);
        userMailMap = getByUserId(userId);
        //}
        LoggerUtils.mailLog.info("UserMailMap is null ?" + (userMailMap == null ? true : false));
        if (userMailMap != null) {
            StringBuilder sb = new StringBuilder();
            Iterator<MailUserModel> iter = userMailMap.getMailMap().values().iterator();
            while (iter.hasNext()) {
                MailUserModel mail = iter.next();
                if (mail.getBeginTime() > System.currentTimeMillis()) {
                    continue;
                }
                LoggerUtils.mailLog.info("mailInfo:" + mail.toString());
                sb.append(mail.toString() + ",");
                JoloAuth.JoloAuth_MailItem.Builder mailItem = JoloAuth.JoloAuth_MailItem.newBuilder();
                mailItem.setId(mail.getId());
                mailItem.setTitle(mail.getTitle());
                mailItem.setContent(mail.getContent());
                mailItem.setTime(TimeUtil.getDateToMillis(mail.getCreateTime()));
                mailItem.setIsRead(mail.getIsRead());
                mailItem.addAllAttachmentItem(getMailAtt(mail.getMailConfigId()));
                list.add(mailItem.build());
            }
            LoggerUtils.mailLog.info("mail's size:" + userMailMap.getMailMap().values().size() + "mailInfo:" + sb.toString());
        }
        return list;
    }

    private List<JoloAuth.JoloAuth_MailAwardInfo> getMailAtt(int mailConfigId) {
        List<JoloAuth.JoloAuth_MailAwardInfo> list = MailConfigService.getInstance().getMailAtt(mailConfigId);
        return list;
    }

    /**
     * @param mailIds
     */
    public void delMail(String userId, List<Long> mailIds) {
        UserMailMap userMailMap = getByUserId(userId);
        if (userMailMap != null) {
            Iterator<MailUserModel> iter = userMailMap.getMailMap().values().iterator();
            while (iter.hasNext()) {
                MailUserModel model = iter.next();
                List<JoloAuth.JoloAuth_MailAwardInfo> awardInfs = MailConfigService.getInstance().getMailAtt(model.getMailConfigId());
                log.debug("删除邮件：" + (mailIds.contains(model.getId())) + "==" + awardInfs.size());
                if (mailIds.contains(model.getId())) {//有附件就不能删掉  && awardInfs.size() > 0
                    addAwardRecord(userId, model, new MailAttachmentConfigModel());
                    DBUtil.delMailUser(model.getId());
                    iter.remove();
                }
            }
            //保存
            saveUserMailMap(userId, userMailMap);
        }

    }

    //TODO 增加玩家已领邮件记录(Redis只需要存放userId->mailId(必为没过期邮件))
    public void addAwardRecord(String userId, MailUserModel mail, MailAttachmentConfigModel att) {
        MailUserAwardLogModel awardLog = new MailUserAwardLogModel();
        awardLog.setContent(mail.getContent());
        awardLog.setExpireTime(mail.getExpireTime());
        awardLog.setItemId(att.getItem_id() != null ? att.getItem_id() + "" : "");
        awardLog.setMailConfigId(mail.getMailConfigId());
        awardLog.setSuccAward((byte) 1);
        awardLog.setTitle(mail.getTitle());
        awardLog.setUserId(userId);
        awardLog.setItemNum(att.getNumber() != null ? att.getNumber() : 0);
        DBUtil.insertMailUserAwardLog(awardLog);
    }

    /**
     * 查看邮件（修改邮件状态）
     *
     * @param userId
     * @param mailId
     */
    public boolean checkMail(String userId, Long mailId) {
        boolean re = false;
        UserMailMap userMailMap = getByUserId(userId);
        Iterator<MailUserModel> iter = userMailMap.getMailMap().values().iterator();
        while (iter.hasNext()) {
            MailUserModel model = iter.next();
            if (model.getId() == mailId) {
                model.setIsRead((byte) 1);
                int result = DBUtil.updateMailUserByPrimaryKey(model);
                if (result > 0) {
                    re = true;
                }
            }
        }
        //保存
        saveUserMailMap(userId, userMailMap);
        return re;
    }

    /**
     * 邮件奖励
     *
     * @param userId
     * @param mailIds
     */
    public void mailAward(String userId, List<Long> mailIds) {

    }

    public UserMailMap getByUserId(String userId) {
        UserMailMap userMailMap = StoredObjManager.hget(RedisConst.MAIL_USER.getProfix(),
                RedisConst.MAIL_USER.getField() + userId,
                UserMailMap.class);
        return userMailMap;
    }

    public UserAwardMap getUserAwardMap(String userId) {
        UserAwardMap userAwardMap = StoredObjManager.hget(RedisConst.MAIL_USER_AWARD_LOG.getProfix(),
                RedisConst.MAIL_USER_AWARD_LOG.getField() + userId, UserAwardMap.class);
        return userAwardMap;
    }

    private Set<Integer> getMailConfigIds(String userId) {
        Set<Integer> set = new HashSet<>();
        User user = StoredObjManager.hget(RedisConst.USER_INFO.getProfix(), RedisConst.USER_INFO.getField() + userId, User.class);
        MailArgsMap mailArgsMap = MailConfigService.getInstance().getMailArgsMap();
        if (mailArgsMap == null) {
            log.debug("mailArgsMap is null");
            return set;
        }
        Iterator<Integer> iterator = mailArgsMap.getAllMailArgs().keySet().iterator();
        while (iterator.hasNext()) {
            Integer key = iterator.next();
            List<MailArgsModel> args = mailArgsMap.getByMailConfigId(key);
            boolean b1 = getResultByType(args, user, 1);
            if (!b1) {
                continue;
            }
            boolean b2 = getResultByType(args, user, 2);
            if (!b2) {
                continue;
            }
            boolean b3 = getResultByType(args, user, 3);
            if (!b3) {
                continue;
            }
            if (b1 && b2 && b3) {
                set.add(key);
            }
        }
        return set;
    }

    private boolean getResultByType(List<MailArgsModel> args, User user, int type) {
        boolean pass = false;
        String typeName = "";
        switch (type) {
            case 1:
                typeName = "channel";
                break;
            case 2:
                typeName = "version";
                break;
            case 3:
                typeName = "packName";
                break;
        }
        Iterator<MailArgsModel> iter = args.iterator();
        while (iter.hasNext()) {
            MailArgsModel m = iter.next();
            if (m.getType() == type) {
                log.debug(typeName + ":" + m.getValue() + ",user's channel:{},version:{},packName:{}", user.getDown_platform(), user.getClient_version(), user.getPackage_name());
                if (m.getValue().equals(user.getDown_platform()) ||
                        m.getValue().equals(user.getClient_version()) ||
                        m.getValue().equals(user.getPackage_name())) {
                    pass = true;
                    break;
                }
            }
        }
        return pass;
    }

    private boolean isContain(Set<Integer> set, Integer mailConfigId) {
        Iterator<Integer> iter = set.iterator();
        while (iter.hasNext()) {
            int id = iter.next();
            if (id == mailConfigId) {
                return true;
            }
        }
        return false;

    }


    private void checkNewMail(String userId, UserMailMap userMailMap) {
        if (userMailMap == null) {
            return;
        }
        UserAwardMap userAwardMap = getUserAwardMap(userId);

        log.debug("开始插入玩家邮件数据：================");
        Set<Integer> set = getMailConfigIds(userId);
        log.debug("userId:{},set:{}", userId, set.toString());
        List<MailConfigModel> list = MailConfigService.getInstance().getAllMailConfig();
        log.debug("mailConfigList size:{}", list.size());
        Iterator<MailConfigModel> iter = list.iterator();
        while (iter.hasNext()) {
            MailConfigModel model = iter.next();
            log.debug(model.toString());
            if (model.getState_control() == 0 ||
                    System.currentTimeMillis() >= model.getExpire_time()) {//没有启用or过期邮件
                userMailMap.del(model.getId());
                saveUserMailMap(userId, userMailMap);
                log.debug("stateControl:{},assign:{},nowSize:{}",
                        model.getState_control(), model.getAssign(), userMailMap.getMailMap().size());
                continue;
            }
            if (model.getAssign() == 1) {//指定邮件
                continue;
            }
            if (!isContain(set, model.getId())) {//渠道、版本、包名不符
                continue;
            }
            if (userMailMap.isContainsKey(model.getId())) {
                continue;
            }
            if (userAwardMap != null && userAwardMap.isContainsKey(model.getId())) {
                continue;
            }

            MailUserModel mailUserModel = new MailUserModel();
            mailUserModel.setContent(model.getContent());
            mailUserModel.setIsRead((byte) 0);
            mailUserModel.setMailConfigId(model.getId());
            mailUserModel.setTitle(model.getTitle());
            mailUserModel.setUserId(userId);
            mailUserModel.setCreateTime(new Date(model.getEstablishl_time()));
            mailUserModel.setExpireTime(model.getExpire_time());
            mailUserModel.setBeginTime(model.getCreate_time());
            MailUserModel result = DBUtil.insertMailUser(userId, mailUserModel);
            if (result != null) {
                userMailMap.put(result);
            }
            LoggerUtils.mailLog.info("checkNewMail()：mailUserModel:{}" + mailUserModel.toString());
        }

    }


    private void loadMailUserAwardLog() {
        MailConfigMap mailConfigMap = MailConfigService.getInstance().getMailConfigMap();
        Iterator<MailConfigModel> iter = mailConfigMap.getAllMail().values().iterator();
        while (iter.hasNext()) {
            MailConfigModel mailConfigModel = iter.next();
            if (mailConfigModel.getState_control() == 0) {
                continue;
            }
            loadMailUserAwardLogFromDB(mailConfigModel.getId());
        }
    }

    private void loadMailUserAwardLogFromDB(int mailConfigId) {
        List<MailUserAwardLogModel> list = DBUtil.getMailUserAwardLogFromDb(mailConfigId);
        if (list == null) {
            return;
        }
        Iterator<MailUserAwardLogModel> iter = list.iterator();
        while (iter.hasNext()) {
            MailUserAwardLogModel mailUserAwardLog = iter.next();
            UserAwardMap userAwardMap = StoredObjManager.hget(RedisConst.MAIL_USER_AWARD_LOG.getProfix(),
                    RedisConst.MAIL_USER_AWARD_LOG.getField() + mailUserAwardLog.getUserId(), UserAwardMap.class);
            if (userAwardMap == null) {
                userAwardMap = new UserAwardMap();
            }
            userAwardMap.put(mailUserAwardLog.getMailConfigId());
            StoredObjManager.hset(RedisConst.MAIL_USER_AWARD_LOG.getProfix(),
                    RedisConst.MAIL_USER_AWARD_LOG.getField() + mailUserAwardLog.getUserId(), userAwardMap);
        }
    }

    public void saveUserMailMap(String userId, UserMailMap userMailMap) {
        StoredObjManager.hset(RedisConst.MAIL_USER.getProfix(), RedisConst.MAIL_USER.getField() + userId, userMailMap);
    }


    private static class SingletonHolder {
        protected static final MailService instance = new MailService();
    }

    public static final MailService getInstance() {
        return MailService.SingletonHolder.instance;
    }
}
